home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
public
/
fax
/
src
/
faxd
/
Class20.c++
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
7KB
|
243 lines
/* $Header: /usr/people/sam/fax/faxd/RCS/Class20.c++,v 1.8 1994/04/25 16:10:06 sam Rel $ */
/*
* Copyright (c) 1994 Sam Leffler
* Copyright (c) 1994 Silicon Graphics, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee, provided
* that (i) the above copyright notices and this permission notice appear in
* all copies of the software and related documentation, and (ii) the names of
* Sam Leffler and Silicon Graphics may not be used in any advertising or
* publicity relating to the software without the specific, prior written
* permission of Sam Leffler and Silicon Graphics.
*
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*
* IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
* ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*/
#include "Class20.h"
#include "ModemConfig.h"
#include <stdlib.h>
#include <ctype.h>
Class20Modem::Class20Modem(FaxServer& s, const ModemConfig& c) : Class2Modem(s,c)
{
serviceType = SERVICE_CLASS20;
setupDefault(classCmd, conf.class2Cmd, "+FCLASS=2.0");
setupDefault(mfrQueryCmd, conf.mfrQueryCmd, "+FMI?");
setupDefault(modelQueryCmd, conf.modelQueryCmd, "+FMM?");
setupDefault(revQueryCmd, conf.revQueryCmd, "+FMR?");
setupDefault(dccQueryCmd, conf.class2DCCQueryCmd, "+FCC=?");
setupDefault(abortCmd, conf.class2AbortCmd, "KS");
setupDefault(borCmd, conf.class2BORCmd, "BO=0");
setupDefault(tbcCmd, conf.class2TBCCmd, "PP=0");
setupDefault(crCmd, conf.class2CRCmd, "CR=1");
setupDefault(phctoCmd, conf.class2PHCTOCmd, "CT=30");
setupDefault(bugCmd, conf.class2BUGCmd, "BU=1");
setupDefault(lidCmd, conf.class2LIDCmd, "LI");
setupDefault(dccCmd, conf.class2DCCCmd, "CC");
setupDefault(disCmd, conf.class2DISCmd, "IS");
setupDefault(cigCmd, conf.class2CIGCmd, "PI");
setupDefault(splCmd, conf.class2SPLCmd, "SP");
// ignore procedure interrupts
setupDefault(pieCmd, conf.class2PIECmd, "IE=0");
// enable reporting of everything
setupDefault(nrCmd, conf.class2NRCmd, "NR=1,1,1,1");
}
Class20Modem::~Class20Modem()
{
}
ATResponse
Class20Modem::atResponse(char* buf, long ms)
{
if (FaxModem::atResponse(buf, ms) == AT_OTHER &&
(buf[0] == '+' && buf[1] == 'F')) {
if (strneq(buf, "+FHS:", 5)) {
processHangup(buf+5);
lastResponse = AT_FHNG;
} else if (strneq(buf, "+FCO", 4))
lastResponse = AT_FCON;
else if (strneq(buf, "+FPO", 4))
lastResponse = AT_FPOLL;
else if (strneq(buf, "+FVO", 4))
lastResponse = AT_FVO;
else if (strneq(buf, "+FIS:", 5))
lastResponse = AT_FDIS;
else if (strneq(buf, "+FNF:", 5))
lastResponse = AT_FNSF;
else if (strneq(buf, "+FCI:", 5))
lastResponse = AT_FCSI;
else if (strneq(buf, "+FPS:", 5))
lastResponse = AT_FPTS;
else if (strneq(buf, "+FCS:", 5))
lastResponse = AT_FDCS;
else if (strneq(buf, "+FNS:", 5))
lastResponse = AT_FNSS;
else if (strneq(buf, "+FTI:", 5))
lastResponse = AT_FTSI;
else if (strneq(buf, "+FET:", 5))
lastResponse = AT_FET;
}
return (lastResponse);
}
/*
* Abort a data transfer in progress.
*/
void
Class20Modem::abortDataTransfer()
{
char c = CAN;
putModemData(&c, 1);
}
/*
* Send a page of data using the ``stream interface''.
*/
fxBool
Class20Modem::sendPage(TIFF* tif)
{
fxBool rc = TRUE;
protoTrace("SEND begin page");
if (flowControl == FLOW_XONXOFF)
setXONXOFF(FLOW_XONXOFF, FLOW_NONE, ACT_FLUSH);
/*
* Correct bit order of data if not what modem expects.
*/
u_short fillorder;
TIFFGetFieldDefaulted(tif, TIFFTAG_FILLORDER, &fillorder);
const u_char* bitrev = TIFFGetBitRevTable(fillorder != conf.sendFillOrder);
u_long* stripbytecount;
(void) TIFFGetField(tif, TIFFTAG_STRIPBYTECOUNTS, &stripbytecount);
for (u_int strip = 0; strip < TIFFNumberOfStrips(tif) && rc; strip++) {
u_int totbytes = (u_int) stripbytecount[strip];
if (totbytes > 0) {
u_char* data = new u_char[totbytes];
if (TIFFReadRawStrip(tif, strip, data, totbytes) >= 0) {
/*
* Pass data to modem, filtering DLE's and
* being careful not to get hung up.
*/
beginTimedTransfer();
rc = putModemDLEData(data, totbytes, bitrev, getDataTimeout());
endTimedTransfer();
protoTrace("SENT %d bytes of data", totbytes);
}
delete data;
}
}
if (!rc)
abortDataTransfer();
if (flowControl == FLOW_XONXOFF)
setXONXOFF(FLOW_CURRENT, FLOW_XONXOFF, ACT_DRAIN);
protoTrace("SEND end page");
return (rc);
}
/*
* Handle the page-end protocol.
*/
fxBool
Class20Modem::pageDone(u_int ppm, u_int& ppr)
{
static char ppmCodes[3] = { 0x2C, 0x3B, 0x2E };
char eop[2];
fxBool seenHangup = FALSE;
eop[0] = DLE;
eop[1] = ppmCodes[ppm];
ppr = 0; // something invalid
if (putModemData(eop, sizeof (eop))) {
for (;;) {
switch (atResponse(rbuf, conf.pageDoneTimeout)) {
case AT_OK: // page data good
case AT_ERROR: // page data bad
if (seenHangup) {
/*
* Cannot query modem for post-page
* response after hangup, so simulate
* it here.
*/
ppr = PPR_MCF;
} else {
fxStr ps;
if (atQuery("+FPS?", ps, 500))
ppr = atoi(ps);
}
return (TRUE);
case AT_FHNG:
if (!isNormalHangup())
return (FALSE);
seenHangup = TRUE;
break;
case AT_EMPTYLINE:
case AT_TIMEOUT:
case AT_NOCARRIER:
case AT_NODIALTONE:
case AT_NOANSWER:
goto bad;
}
}
}
bad:
processHangup("50"); // Unspecified Phase D error
return (FALSE);
}
/*
* Receive DLE-escaped data from the modem.
*/
fxBool
Class20Modem::recvPageDLEData(TIFF* tif)
{
fxBool prematureEOF = FALSE;
u_char buf[16*1024];
int n = 0;
for (;;) {
int b = getModemDataChar();
if (b == EOF) {
protoTrace("RECV: premature EOF");
prematureEOF = TRUE;
break;
}
if (b == DLE) {
b = getModemDataChar();
if (b == EOF || b == ETX) {
if (b == EOF) {
prematureEOF = TRUE;
protoTrace("RECV: premature EOF");
}
break;
}
if (b != DLE) {
if (n == sizeof (buf))
recvData(tif, buf, sizeof (buf)), n = 0;
buf[n++] = DLE;
// Class 2.0 requires <DLE><SUB> be converted to <DLE><DLE>
if (b == SUB)
b = DLE;
}
}
if (n == sizeof (buf))
recvData(tif, buf, sizeof (buf)), n = 0;
buf[n++] = b;
}
if (n > 0)
recvData(tif, buf, n);
return (prematureEOF);
}